﻿using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using BreukTrainer.BreukModel;
using BreukTrainer.Controller;

namespace BreukTrainer.View
{
    public partial class Oefenen_met_breuken : Form
    {
        private MaakBreukenController maakBreukenController;
        private OpgaveController oc;

        public Oefenen_met_breuken()
        {
            InitializeComponent();

            maakBreukenController = new MaakBreukenController();

            textOndergrens.Tag = false;
            textBovengrens.Tag = false;
            textAantalOpgaves.Tag = false;
            textTijd.Tag = false;

            textOndergrens.TextChanged += new System.EventHandler(textEmpty_TextChanged);
            textOndergrens.KeyPress += new System.Windows.Forms.KeyPressEventHandler(textInteger_KeyPress);
            textOndergrens.TextChanged += new System.EventHandler(ValidateMaakBreukenEenvoudig);

            textBovengrens.TextChanged += new System.EventHandler(textEmpty_TextChanged);
            textBovengrens.KeyPress += new System.Windows.Forms.KeyPressEventHandler(textInteger_KeyPress);
            textBovengrens.TextChanged += new System.EventHandler(ValidateMaakBreukenEenvoudig);

            textAantalOpgaves.TextChanged += new System.EventHandler(textEmpty_TextChanged);
            textAantalOpgaves.KeyPress += new System.Windows.Forms.KeyPressEventHandler(textInteger_KeyPress);
            textAantalOpgaves.TextChanged += new System.EventHandler(ValidateMaakOpgaves);

            textTijd.TextChanged += new System.EventHandler(textEmpty_TextChanged);
            textTijd.KeyPress += new System.Windows.Forms.KeyPressEventHandler(textInteger_KeyPress);
            textTijd.TextChanged += new System.EventHandler(ValidateMaakOpgaves);
            
            //maak breuken
            btnMaakBreuken.Click += new System.EventHandler(activateBtnMaakBreuken);
            btnMaakBreukenEenvoudig.Click += new System.EventHandler(activateBtnMaakBreuken);

            //maak opgaven
            chkTijdsLimiet.CheckedChanged += new System.EventHandler(tijdslimiet_CheckedChanged);

            textEmpty_TextChanged(textTijd, new EventArgs());
            textEmpty_TextChanged(textAantalOpgaves, new EventArgs());

            this.btnOplossingen.Click += new System.EventHandler(this.btnEvalueer_Click);//Ook evalueren bij Click btnOplossingen
        }

        private void rdbZelfInvoeren_CheckedChanged(object sender, EventArgs e)
        {
            //TODO rdbZelfInvoeren: dit laten werken, of niet (zie opmerk.)
            //Wat is de bedoeling, dat dataGridViewBreuken enkel kan aangepast worden wanneer ZelfInvoeren gekozen is?
            //Nu kan de breuk aangepast worden wanneer er geen goede zijn gegenereerd. Dus dit is niet nodig volgens mij.
            //dataGridViewBreuken.ReadOnly = !((RadioButton)sender).Checked;//<-Zo werkt het wel.
        }

        private void rdbGenereren_CheckedChanged(object sender, EventArgs e)
        {
            btnMaakBreuken.Enabled = ((RadioButton)sender).Checked;
        }

        private void rdbGenererenEenvoudig_CheckedChanged(object sender, EventArgs e)
        {
            textBovengrens.Enabled = rdbGenererenEenvoudig.Checked;
            textOndergrens.Enabled = rdbGenererenEenvoudig.Checked;
            ValidateMaakBreukenEenvoudig(sender, e);
        }

        private void textEmpty_TextChanged(object sender, EventArgs e)
        {
            TextBox tb = (TextBox)sender;
            if (tb.Text.Length == 0)
            {
                tb.Tag = false;
            }
            else
            {
                tb.Tag = true;
            }
        }

        private void textInteger_KeyPress(object sender, KeyPressEventArgs e)
        {
            if((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8)
                e.Handled = true;
        }

        private void ValidateMaakBreukenEenvoudig(object sender, EventArgs e)
        {
            btnMaakBreukenEenvoudig.Enabled = (bool)textOndergrens.Tag &&
                                                (bool)textBovengrens.Tag &&
                                                rdbGenererenEenvoudig.Checked;
        }

        private void ValidateMaakOpgaves(object sender, EventArgs e)
        {
            bool enabled = true;

            if (chkTijdsLimiet.Checked && !(bool)textTijd.Tag)
                enabled = false;

            if (rdbRandomBewerking.Checked && !(bool)textAantalOpgaves.Tag)
                enabled = false;

            btnMaakOpgaves.Enabled = enabled;
        }

        private void activateBtnMaakBreuken(object sender, EventArgs e)
        {
            groupBoxBewerkingen.Enabled = true;
        }

        private void tijdslimiet_CheckedChanged(object sender, EventArgs e)
        {
            textTijd.Enabled = ((CheckBox)sender).Checked;
            ValidateMaakOpgaves(sender, e);
        }

        private void activateBtnMaakOpgaven(object sender, EventArgs e)
        {
            btnMaakOpgaves.Enabled = true;
        }

        private void btnMaakBreuken_Click(object sender, EventArgs e)
        {
            maakBreukenController = new MaakBreukenController();
            int n = (int)numericUpDownAantalBreuken.Value;

            //onder en bovengrens zijn hier niet bepaald kheb nu 0 en  20 genmen maar dat kan 
            //later nog verranderd worden
            maakBreukenController.GenereerBreuken(n, 0, 20);

            UpdateDataGridViewBreuken();
        }

        private void btnMaakBreukenEenvoudig_Click(object sender, EventArgs e)
        {
            //eerst zorgen dat de onder en bovengrens juist bepaald zijn
            int onder = int.Parse(textOndergrens.Text);
            int boven = int.Parse(textBovengrens.Text);
            maakBreukenController = new MaakBreukenController(onder, boven);

            //en dan maar breuken genereren!
            int n = (int)numericUpDownAantalBreuken.Value;
            maakBreukenController.GenereerBreuken(n, onder, boven);

            UpdateDataGridViewBreuken();
        }

        private void UpdateDataGridViewBreuken()
        {
            int count = dataGridViewBreuken.Rows.Count;
            for (int i = 0; i < maakBreukenController.Breukcontainer.Breuken.Count; i++ )
            {
                Breuk b = maakBreukenController.Breukcontainer[i];
                dataGridViewBreuken.Rows.Add(count + i, b.ToString());
            }
            dataGridViewBreuken.Update();

            //de breuken in de dataGridViewGesorteerd zetten
            count = dataGridViewBreuken.Rows.Count;
            count--;//anders voegen we de lege rij die er op het einde bijkomt ook toe, en als we dat doen huilt baby jezus, en dat is  niet cool
            for (int i = 0; i < count; i++)
            {
                dataGridViewGesorteerd.Rows.Add(dataGridViewBreuken.Rows[i].Cells[1].Value);
            }
        }

        private void btnMaakOpgaves_Click(object sender, EventArgs e)
        {
            int count = dataGridViewBreuken.Rows.Count - 1;
            int aantalopgaves = 4;
            dataGridViewAntwoorden.Rows.Clear();
            if (rdbRandomBewerking.Checked) {
                aantalopgaves = int.Parse(textAantalOpgaves.Text);
            }
            oc = new OpgaveController(aantalopgaves,count);
            for (int i = 0; i < count; i++)
            {
                try
                {
                    //de stringvalue van elke rij parse'n naar een breuk
                    oc.Add(Breuk.Parse(dataGridViewBreuken.Rows[i].Cells[1].Value.ToString()));
                }
                catch (ArgumentException ex)
                {
                    Debug.WriteLine(ex.Message);
                    oc.AantalBreuken = oc.AantalBreuken - 1;
                }
            }
            if (rdbRandomBewerking.Checked)
            {
                oc.RandomOpgaves();
            }
            else {
                oc.BasicOpgaves();
            } 
            for (int i = 0; i < aantalopgaves; i++)
            {
                dataGridViewAntwoorden.Rows.Add(oc.ToonOpgave(i));
            }
            //starten timer
            if (chkTijdsLimiet.Checked)
            {
                prgBarAntwoord.Enabled = true;
                prgBarAntwoord.Maximum = int.Parse(textTijd.Text);
                prgBarAntwoord.Step = timerAntwoord.Interval / 1000;
                prgBarAntwoord.Value = 0;
                timerAntwoord.Enabled=true;
            }
        }

        private void dataGridViewBreuken_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            int count = dataGridViewBreuken.Rows.Count-1;
            dataGridViewBreuken.Rows[count-1].Cells[0].Value = count;
            groupBoxBewerkingen.Enabled = true;
        }

        private void btnEvalueer_Click(object sender, EventArgs e)
        {
            //Stop de klok
            timerAntwoord.Enabled = false;
            //haal focus weg van cell (kleur blauw)
            dataGridViewAntwoorden.ClearSelection();

            int count = dataGridViewAntwoorden.Rows.Count;
            for (int i = 0; i < count; i++)
            {
                try
                {
                    if (Breuk.Parse(oc.ToonOplossing(i)).Equals(Breuk.Parse(dataGridViewAntwoorden.Rows[i].Cells[1].Value.ToString())))
                    {
                        dataGridViewAntwoorden.Rows[i].Cells[1].Style.BackColor = Color.Green;
                    }
                    else
                    {
                        dataGridViewAntwoorden.Rows[i].Cells[1].Style.BackColor = Color.Red;
                    }
                }
                catch (Exception ex)//antwoord is leeg of onmogelijk
                {
                    dataGridViewAntwoorden.Rows[i].Cells[1].Style.BackColor = Color.Red;
                }
            }
        }
        private void btnOplossingen_Click(object sender, EventArgs e)
        {
            int count = dataGridViewAntwoorden.Rows.Count;
            for (int i = 0; i < count; i++)
            {
                try
                {
                    if (!Breuk.Parse(oc.ToonOplossing(i)).Equals(Breuk.Parse(dataGridViewAntwoorden.Rows[i].Cells[1].Value.ToString())))
                    {
                        dataGridViewAntwoorden.Rows[i].Cells[2].Value = oc.ToonOplossing(i);
                    }
                }
                catch (Exception ex)//antwoord is leeg of onmogelijk
                {
                    dataGridViewAntwoorden.Rows[i].Cells[2].Value = oc.ToonOplossing(i);
                }
            }
        }

        private void btnSorteerOmhoog_Click(object sender, EventArgs e)
        {
            Sorteer(true);    
        }

        private void btnSorteerOmlaag_Click(object sender, EventArgs e)
        {
            Sorteer(false);
        }

        private void Sorteer(bool omhoog)
        {
            int count = dataGridViewGesorteerd.Rows.Count;
            BreukContainer bc = new BreukContainer();

            for (int i = 0; i < count; i++)
            {
                try
                {
                    bc.Add(Breuk.Parse((String)dataGridViewGesorteerd.Rows[i].Cells[0].Value));
                }
                catch (ArgumentException ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }

            int j = 0;
            foreach (Breuk b in bc.Sorteer(omhoog))
            {
                dataGridViewGesorteerd.Rows[j].Cells[0].Value = b.ToString();
                j++;
            }
        }

        private void rdbRandomBewerking_CheckedChanged(object sender, EventArgs e)
        {
            textAantalOpgaves.Enabled = ((RadioButton)sender).Checked;
            ValidateMaakOpgaves(sender, e);
        }

        private void timerTick(object sender, EventArgs e)
        {
            prgBarAntwoord.PerformStep();
            if (prgBarAntwoord.Value == prgBarAntwoord.Maximum)
            {
                timerAntwoord.Enabled = false;
                btnEvalueer_Click(sender, e);
            }
        }

        private void dataGridViewAntwoorden_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (timerAntwoord.Enabled &&((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
            {
                ((DataGridView)sender).Rows[e.RowIndex].ReadOnly = true;
                prgBarAntwoord.Value = 0;
            }
        }

        private void dataGridViewBreuken_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (((DataGridView)sender).RowCount > 1)
            {
                Regex reg = new Regex("^-?\\d+(/([1-9]|\\d{2,}))?$");
                if (!reg.IsMatch(((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString()))
                {
                    ((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value = "";//UNDONE dataGridViewBreuken: Wat invullen wanneer breuk fout is? Nu: wissen breuk
                    //((DataGridView)sender).CurrentCell = ((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex];
                }
            }
        }
    }
}
